package com.dyna.gateway.listener;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.dyna.constants.EsIndicesConstant;
import com.dyna.constants.TopicConstant;
import com.dyna.core.utils.CollUtil;
import com.dyna.core.utils.JsonUtil;
import com.dyna.gateway.config.properties.IgnoreWhiteProperties;
import com.dyna.launch.utils.INetUtil;
import com.dyna.utils.EsUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GatewayLogConsumerListener {

    @Value("${server.port}")
    private int port;

    @Resource
    private IgnoreWhiteProperties ignoreWhiteProperties;

    private static final TypeReference<Map<String, Object>> MAP_TYPE_REFERENCE = new TypeReference<Map<String, Object>>() {};

    @KafkaListener(topics = TopicConstant.GATEWAY_LOG_INDEX, groupId = "group")
    public void consumerMsg(String msg) {
        Map<String, Object> map = JsonUtil.parseObject(msg, MAP_TYPE_REFERENCE);

        // 不统计白名单接口日志
        List<String> gatewayLogWhite = Arrays.stream(ignoreWhiteProperties.getLogWhites()).collect(Collectors.toList());
        String requestUrl = (String)map.getOrDefault("requestUrl", "");
        if (CollUtil.isNotEmpty(gatewayLogWhite) && gatewayLogWhite.contains(requestUrl)) {
            return;
        }
        String curl = generateCurlCommand(map);
        map.put("curl", curl);
        EsUtil.addData(EsIndicesConstant.GATEWAY_LOG_INDEX, map);
        log.info("\n[writeAccessLog 网关日志]\n{}", JSON.toJSONString(map));
    }

    /**
     * 根据给定的 values 构建 curl 命令字符串。
     */
    public String generateCurlCommand(Map<String, Object> values) {
        StringBuilder curl = new StringBuilder("CURL ");
        curl.append("-X  ").append(values.get("requestMethod")).append(" ");

        // 2. 组装 URL（包含查询参数）
        String requestUrl = (String) values.get("requestUrl");
        requestUrl = values.get("schema") + "://"+ INetUtil.getHostIp()+ ":" + port + requestUrl;
        Map<String, String> queryParams = (Map<String, String>) values.get("queryParams");
        String finalUrl = appendQueryParams(requestUrl, queryParams);
        curl.append("'").append(finalUrl).append("' ");

        // 3. 添加请求头
        Map<String, List<String>> requestHeaders = JSON.parseObject((String) values.get("requestHeaders"), Map.class);
        boolean hasContentType = false;
        if (!MapUtil.isEmpty(requestHeaders))  {
            for (Map.Entry<String, List<String>> entry : requestHeaders.entrySet()) {
                String key = entry.getKey();
                if (CollUtil.isNotEmpty(entry.getValue())) {
                    if ("Content-Length".equalsIgnoreCase(key)) {
                        continue;
                    }
                    curl.append("-H  '").append(key).append(": ").append(entry.getValue().get(0)).append("' ");
                    if ("Content-Type".equalsIgnoreCase(key)) {
                        hasContentType = true;
                    }
                }

            }
        }

        Object requestBodyObj = values.get("requestBody");
        boolean hasBody = requestBodyObj != null && requestBodyObj instanceof Map && !((Map<?, ?>) requestBodyObj).isEmpty();
        // 4. 添加 Content-Type: application/json（如果未指定）
        if (hasBody && !hasContentType) {
            curl.append("-H  'Content-Type: application/json' ");
        }

        // 5. 添加请求体
        if (hasBody) {
            String requestBodyStr = JSONUtil.toJsonStr(requestBodyObj);
            curl.append("-d  '").append(requestBodyStr).append("' ");
        }
        return curl.toString().trim();
    }

    /**
     * 拼接查询参数到 URL 上，替换原有查询参数。
     */
    private static String appendQueryParams(String url, Map<String, String> queryParams) {
        if (queryParams == null || queryParams.isEmpty())  {
            return url;
        }

        List<String> params = new ArrayList<>();
        for (Map.Entry<String, String> entry : queryParams.entrySet())  {
            String encodedKey = URLUtil.encode(entry.getKey());
            String encodedValue = URLUtil.encode(entry.getValue());
            params.add(encodedKey  + "=" + encodedValue);
        }

        String queryString = String.join("&",  params);
        if (url.contains("?"))  {
            int questionMarkIndex = url.indexOf('?');
            return url.substring(0,  questionMarkIndex) + "?" + queryString;
        } else {
            return url + "?" + queryString;
        }
    }

}
